package me.suntao.javaio.server.nio;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 非阻塞IO
 * Created by suntao on 2017/6/2.
 */
public class NioEchoServer {

  private static final int DEFAULT_PORT = 28000;

  public static void main(String[] args){
    ServerSocketChannel serverChannel;
    Selector selector;
    try {
      serverChannel = ServerSocketChannel.open();
      InetSocketAddress address = new InetSocketAddress(DEFAULT_PORT);
      serverChannel.bind(address);
      //设置channel为非阻塞
      serverChannel.configureBlocking(false);
      //通道管理器
      selector = Selector.open();
      //将通道管理器和该通道绑定，并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,当该事件到达时，selector.select()会返回，如果该事件没到达selector.select()会一直阻塞
      serverChannel.register(selector, SelectionKey.OP_ACCEPT);
      //轮询监听selector事件
      while (true){
        //当注册的事件到达时，方法返回；否则,该方法会一直阻塞
        selector.select();
        //获得selector中选中的项的迭代器，选中的项为注册的事件
        Set<SelectionKey> readyKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = readyKeys.iterator();

        while (iterator.hasNext()){
          SelectionKey key = iterator.next();
          //删除已选的key,以防重复处理
          iterator.remove();
          //客户端请求连接事件
          if(key.isAcceptable()){
            //获得和客户端连接的通道
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel client = server.accept();
            System.out.println(System.currentTimeMillis()+", Accepted connection from " + client);
            //同样设为非堵塞
            client.configureBlocking(false);
            //给通道设置读写的权限
            SelectionKey clientKey = client.register(selector,
              SelectionKey.OP_WRITE | SelectionKey.OP_READ);
            ByteBuffer buffer = ByteBuffer.allocate(200);
            clientKey.attach(buffer);
          }
          if(key.isReadable()){
            //处理读取客户端发来的信息 的事件
            SocketChannel client = (SocketChannel) key.channel();
            ByteBuffer output = (ByteBuffer) key.attachment();
            int count = client.read(output);
            if(count>0) {
              output.flip();
              byte[] data = output.array();
              String msg = new String(data, "UTF-8");
              System.out.println("client msg:" + msg.trim());
              ByteBuffer outBuffer =  ByteBuffer.wrap(("server msg:"+System.currentTimeMillis()).getBytes("UTF-8"));
              client.write(outBuffer);
            }
          }
        }
      }
    } catch (IOException e) {

      e.printStackTrace();
    }
  }
}
